package com.xiaoye.app.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.xiaoye.app.annotation.AspectAnnotation;
import com.xiaoye.app.common.MsgReturn;

//声明这是一个组件
@Component
// 声明这是一个切面Bean
@Aspect
public class ServiceAspect {

	private static Logger log = Logger.getLogger(ServiceAspect.class);

	// 配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
	// @Pointcut("execution(* isSuccess(..))")
	@Pointcut("@annotation(com.wiseparent.app.annotation.AspectAnnotation)")
	public void aspect() {
	}

	/*
	 * 配置前置通知,使用在方法aspect()上注册的切入点 同时接受JoinPoint切入点对象,可以没有该参数
	 */
	@Before("aspect()")
	public void before(JoinPoint joinPoint) {
		// System.out.println("before");
		System.out.println(
				((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(AspectAnnotation.class).test());
	}

	// 配置后置通知,使用在方法aspect()上注册的切入点
	@After("aspect()")
	public void after(JoinPoint joinPoint) {
		// System.out.println("after");
		System.out.println(
				((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(AspectAnnotation.class).test());
		if (log.isInfoEnabled()) {
			log.info("after " + joinPoint);
		}
	}

	// 配置环绕通知,使用在方法aspect()上注册的切入点
	@Around("aspect()")
	public MsgReturn around(ProceedingJoinPoint joinPoint) {
		// System.out.println("around start");
		long start = System.currentTimeMillis();
		try {
			MsgReturn result = (MsgReturn) joinPoint.proceed();
			long end = System.currentTimeMillis();
			if (log.isInfoEnabled()) {
				log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
			}
			// System.out.println("around end");
			return result;
		} catch (Throwable e) {
			long end = System.currentTimeMillis();
			if (log.isInfoEnabled()) {
				log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : "
						+ e.getMessage());
			}
		}
		return null;
	}
	//
	// //配置后置返回通知,使用在方法aspect()上注册的切入点
	// @AfterReturning("aspect()")
	// public void afterReturn(JoinPoint joinPoint){
	// System.out.println("afterReturn");
	// System.out.println(joinPoint.getArgs()[0]);
	// if(log.isInfoEnabled()){
	// log.info("afterReturn " + joinPoint);
	// }
	// }

	// 配置抛出异常后通知,使用在方法aspect()上注册的切入点
	@AfterThrowing(pointcut = "aspect()", throwing = "ex")
	public void afterThrow(JoinPoint joinPoint, Exception ex) {
		// System.out.println("afterThrow");
		if (log.isInfoEnabled()) {
			log.info("afterThrow " + joinPoint + "\t" + ex.getMessage());
		}
	}
}
